package com.lg.concurrent.schedule;

import lombok.SneakyThrows;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;


/**
 *   reentrantLock中的condition 也可以像对象一样wait、notify
 *
 *   每个 reentrantLock 可以创建多个 condition ，condition的优势是分组环境
 *   在await、signal、signalAll之前必须获取这个 reentrantLock的锁
 *
 */
public class ReentrantCondition {

    static  class Run implements Runnable{
        ReentrantLock reentrantLock;
        java.util.concurrent.locks.Condition condition;
        Run(ReentrantLock reentrantLock,  java.util.concurrent.locks.Condition condition){
            this.reentrantLock = reentrantLock;
            this.condition = condition;
        }
        @SneakyThrows
        @Override
        public void run() {
            reentrantLock.lock();
            try {
                System.out.println(Thread.currentThread().getId() + " start" );
                condition.await();
            } catch (Exception e) {
                e.printStackTrace();
            }finally {
                reentrantLock.unlock();
            }
            System.out.println(Thread.currentThread().getId() + " end" );
        }
    }


    private static ReentrantLock reentrantLock = new ReentrantLock();
    private  static java.util.concurrent.locks.Condition condition = reentrantLock.newCondition();
    @SneakyThrows
    public static void main(String[] args) {
        for (int i = 0; i < 3; i++) {
            Thread thread = new Thread(new Run(reentrantLock,condition));
            thread.start();
        }

        System.out.println("main do something");
        TimeUnit.SECONDS.sleep(3);

        reentrantLock.lock();
        try {
            condition.signalAll();
            condition.await();
        }finally {
            reentrantLock.unlock();
        }

        System.out.println("main end");


    }
}
